#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：python_learning 
@File ：测试队列数据报文发送.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2024/12/29 13:29 
"""

import socket
import threading
from queue import Queue
import random
import time
from typing import Any


class DataSender:
	"""
	使用随机生成器作为数据源的socket数据发送模块。
	"""

	def __init__(self, host: str, port: int):
		"""
		初始化DataSender类。

		:param host: 服务器地址。
		:param port: 服务器端口。
		"""
		self.host = host
		self.port = port
		self.data_queue: Queue = Queue()  # 数据队列
		self.running = False  # 运行状态标志
		self.socket = None  # socket对象

	def start(self):
		"""
		启动数据发送线程。
		"""
		self.running = True
		threading.Thread(target=self._send_data).start()

	def stop(self):
		"""
		停止数据发送，关闭socket连接。
		"""
		self.running = False
		if self.socket:
			self.socket.close()

	def _send_data(self):
		"""
		发送队列中的数据到socket。
		"""
		while self.running:
			try:
				if self.socket is None or self.socket.fileno() < 0:
					self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
					self.socket.connect((self.host, self.port))
					print(f"连接到 {self.host}:{self.port}")

				if not self.data_queue.empty():
					data = self.data_queue.get()
					self.socket.sendall(data.encode())
					print(f"发送数据：{data}")
				else:
					time.sleep(0.1)  # 短暂休息，避免CPU占用过高
			except socket.error as e:
				print(f"发送数据时出错：{e}")
				if self.running:
					self.socket.close()
					self.socket = None
					print("尝试重新连接...")
					time.sleep(1)  # 等待1秒后重试
			except Exception as e:
				print(f"发生异常：{e}")
				self.stop()

	def put_data(self, data: str):
		"""
		将数据放入队列。

		:param data: 要发送的数据。
		"""
		self.data_queue.put(data)


# 数据生成器
def data_generator() -> str:
	"""
	生成随机数据的生成器。

	:return: 随机生成的数据。
	"""
	while True:
		yield f"Random Data {random.randint(1, 100)}"


# 主函数
if __name__ == "__main__":
	host = 'localhost'
	port = 12345
	sender = DataSender(host, port)
	sender.start()

	# 使用生成器生成数据
	generator = data_generator()
	try:
		for data in generator:
			sender.put_data(data)
			time.sleep(random.uniform(0.1, 0.5))  # 模拟数据生成时间间隔
	except KeyboardInterrupt:
		sender.stop()
